<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      class Promise {
        constructor(executor) {
          this.state = "pending";
          this.value = undefined;
          this.reason = undefined;

          this.onFullfilledCallbacks = [];
          this.onRejectedCallbacks = [];

          let resolve = (value) => {
            setTimeout(() => {
              if (this.state === "pending") {
                this.state = "fullfilled";
                this.value = value;
                this.onFullfilledCallbacks.forEach((fn) => fn());
              }
            }, 0);
          };
          let reject = (reason) => {
            setTimeout(() => {
              if (this.state === "pending") {
                this.state = "rejected";
                this.reason = reason;
                this.onRejectedCallbacks.forEach((fn) => fn());
              }
            }, 0);
          };
          executor(resolve, reject);
        }

        then(onFullfilled, onRejected) {
          let promise2 = new Promise((resolve, reject) => {
            if (this.state === "fullfilled") {
              let x = onFullfilled(this.value);
              // resolve(x);
              resolvePromise(x, resolve, reject);
            }
            if (this.state === "rejected") {
              let x = onRejected(this.reason);
              resolvePromise(x, resolve, reject);
            }
            if (this.state === "pending") {
              this.onFullfilledCallbacks.push(() => {
                let x = onFullfilled(this.value);
                resolvePromise(x, resolve, reject);
              });
              this.onRejectedCallbacks.push(() => {
                let x = onRejected(this.reason);
                resolvePromise(x, resolve, reject);
              });
            }
          });
          return promise2;
        }
      }

      function resolvePromise(x, resolve, reject) {
        if (x instanceof Promise) {
          x.then(
            (res) => {
              resolve(res);
            },
            (err) => {
              reject(err);
            }
          );
        } else {
          resolve(x);
        }
      }
      const p = new Promise((resolve, reject) => {
        // resolve(200)
        setTimeout(() => {
          resolve(200);
        }, 2000);
      });

      p.then((res) => {
        console.log(res);
        return 300;
      }).then((res) => {
        console.log(res);
      });
    </script>
  </body>
</html>
